﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;

namespace HybridLab.Virtual.Interfaces
{
	internal class VirtualHostContainer
	{
		/// <summary>
		/// MEF injects this value. After Composition this contains all the IVirtualHost implementations.
		/// </summary>
		[ImportMany(typeof(IVirtualHost))]
		private IEnumerable<IVirtualHost> VirtualHosts;

		/// <summary>
		/// An MEF Container that will find all the IVirtualHost implementations in the current directory
		/// </summary>
		internal VirtualHostContainer()
		{
			var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			var dlls = new DirectoryInfo(path).GetFileSystemInfos("*.dll");
			var catalog = new AggregateCatalog();
			foreach (var dll in dlls.Where(d => !(d.Name.StartsWith("System") || d.Name.StartsWith("Microsoft"))))
			{
				try
				{
					var asm = Assembly.LoadFrom(dll.FullName);
					var assemblyCatalog = new AssemblyCatalog(asm);
					if (assemblyCatalog.Parts.Count() > 0)
					{
						catalog.Catalogs.Add(assemblyCatalog);
					}
				}
				catch (Exception)
				{
				}
			}
			new CompositionContainer(catalog).SatisfyImportsOnce(this);
		}

		/// <summary>
		/// Uses MEF to discover IVirtualHost implementations and returns all the Host Types
		/// </summary>
		/// <returns>A List of Host Types available</returns>
		internal List<string> GetHostTypes()
		{
			return (from h in VirtualHosts
					select h.HostType).ToList();
		}

		/// <summary>
		/// Instantiates an IVirtualHost implementation and calls Connect() before returning the host object
		/// </summary>
		/// <param name="hostType">The type of host to connect to</param>
		/// <param name="hostName">The name of the host</param>
		/// <param name="domain">Domain for the credentials</param>
		/// <param name="userName">Username for connection</param>
		/// <param name="password">Password for connection</param>
		/// <returns>An IVirtualHost object</returns>
		internal IVirtualHost GetHost(string hostType, string hostName, string domain = "", string userName = "", string password = "")
		{
			var host = VirtualHosts.Single(h => h.HostType == hostType);
			host.Connect(hostName, domain, userName, password);
			return host;
		}
	}
}
